TOPDIR := ${CURDIR}
ARCH := arm64
CROSS_COMPILE := aarch64-linux-gnu-
job ?= 1

export TOPDIR ARCH CROSS_COMPILE

BUSYBOX-VERSION := 1.36.1
LINUX-VERSION := 6.7.5
JOBS := $(job)

.PHONY: module bare

prepare:
	@mkdir -p dl build_dir ~/.config/gdb
	@[ -f /home/zjh/.config/gdb/gdbinit ] || echo "set auto-load safe-path /" > /home/zjh/.config/gdb/gdbinit

# Build busybox
busybox: prepare build_dir/busybox-$(BUSYBOX-VERSION)/.config
	make -C build_dir/busybox-$(BUSYBOX-VERSION) -j $(JOBS)
	make -C build_dir/busybox-$(BUSYBOX-VERSION) install

build_dir/busybox-$(BUSYBOX-VERSION)/.config: build_dir/busybox-$(BUSYBOX-VERSION)/.prepared
	cp configs/busybox.defconfig build_dir/busybox-$(BUSYBOX-VERSION)/.config
	echo CONFIG_PREFIX="\"$(TOPDIR)/build_dir/rootfs\"" >> build_dir/busybox-$(BUSYBOX-VERSION)/.config
	make -C build_dir/busybox-$(BUSYBOX-VERSION) menuconfig
	cp -r rootfs build_dir
	mkdir -p build_dir/rootfs/dev build_dir/rootfs/lib

build_dir/busybox-$(BUSYBOX-VERSION)/.prepared: dl/busybox-$(BUSYBOX-VERSION).tar.bz2
	tar jxf $< -C build_dir
	cd build_dir/busybox-$(BUSYBOX-VERSION) && quilt import $(TOPDIR)/patchs/busybox/*.patch && quilt push -a
	touch $@

dl/busybox-$(BUSYBOX-VERSION).tar.bz2:
	wget https://www.busybox.net/downloads/busybox-$(BUSYBOX-VERSION).tar.bz2 -O $@

busybox_menuconfig: build_dir/busybox-$(BUSYBOX-VERSION)/.prepared
	make -C build_dir/busybox-$(BUSYBOX-VERSION) menuconfig


# Build linux
kernel: prepare build_dir/linux-$(LINUX-VERSION)/.config
	make -C build_dir/linux-$(LINUX-VERSION) -j $(JOBS)
	make -C build_dir/linux-$(LINUX-VERSION) scripts_gdb

build_dir/linux-$(LINUX-VERSION)/.config: build_dir/linux-$(LINUX-VERSION)/.prepared
	cp configs/kernel.defconfig build_dir/linux-$(LINUX-VERSION)/arch/arm64/configs/qemu_defconfig
	echo CONFIG_INITRAMFS_SOURCE="\"$(TOPDIR)/build_dir/rootfs $(TOPDIR)/initramfs-files.txt\"" \
		>> build_dir/linux-$(LINUX-VERSION)/arch/arm64/configs/qemu_defconfig
	make -C build_dir/linux-$(LINUX-VERSION) qemu_defconfig

build_dir/linux-$(LINUX-VERSION)/.prepared: dl/linux-$(LINUX-VERSION).tar.xz
	tar Jxf $< -C build_dir
	cd build_dir/linux-$(LINUX-VERSION) && quilt import $(TOPDIR)/patchs/kernel/*.patch && quilt push -a
	touch $@

dl/linux-$(LINUX-VERSION).tar.xz:
	wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v6.x/linux-$(LINUX-VERSION).tar.xz -O $@

kernel_defconfig:
	rm build_dir/linux-$(LINUX-VERSION)/.config
	make build_dir/linux-$(LINUX-VERSION)/.config

kernel_menuconfig: build_dir/linux-$(LINUX-VERSION)/.config
	make -C build_dir/linux-$(LINUX-VERSION) menuconfig

save_kernel_config:
	make -C build_dir/linux-$(LINUX-VERSION) savedefconfig
	cp build_dir/linux-$(LINUX-VERSION)/defconfig configs/kernel.defconfig
	sed -i '/CONFIG_INITRAMFS_SOURCE/d' configs/kernel.defconfig


# Build module for test
module:
	make -C build_dir/linux-$(LINUX-VERSION) M=$(TOPDIR)/module modules
	cp module/*.ko mnt


# Bare metal
bare:
	make -C bare


# run qemu
QEMU_BOOT_ARGS := "rdinit=/sbin/init"
QEMU_HD_ARGS :=

ifeq ($(hd),1)
  QEMU_HD_ARGS += -drive if=none,file=$(TOPDIR)/rootfs.bin,id=hd0,format=raw
  QEMU_HD_ARGS += -device virtio-blk-device,drive=hd0
ifeq ($(root),hd)
  # CONFIG_BLK_DEV_INITRD needs to be unselected
  QEMU_BOOT_ARGS := "root=/dev/vda rootfstype=ext4 rw rootwait"
endif
endif

run:
	@mkdir -p mnt
	qemu-system-aarch64 -machine virt -cpu cortex-a57 -nographic \
			-fsdev local,id=fsdev0,security_model=none,path=$(TOPDIR)/mnt \
			-device virtio-9p-pci,fsdev=fsdev0,mount_tag=hostshare \
			-netdev user,id=net0 -net nic,netdev=net0 \
			-kernel build_dir/linux-$(LINUX-VERSION)/arch/arm64/boot/Image \
			$(QEMU_HD_ARGS) \
			-append $(QEMU_BOOT_ARGS) \
			$(if $(mem),-m $(mem)) \
			$(if $(smp),-smp $(smp)) \
			$(if $(dbg),-S -s)
